package com.zheng1.envii.btutils

import android.annotation.SuppressLint
import android.bluetooth.BluetoothAdapter
import android.bluetooth.BluetoothDevice
import android.bluetooth.BluetoothManager
import android.bluetooth.le.ScanCallback
import android.bluetooth.le.ScanFilter
import android.bluetooth.le.ScanResult
import android.bluetooth.le.ScanSettings
import android.content.Context
import android.os.Handler
import android.os.Looper
import android.os.ParcelUuid
import android.util.Log
import java.util.UUID

class BleHelper (context: Context) {

    private val TAG = "BleHelper"
    private val _context = context
    private var _scanning = false
    private val _SCAN_PERIOD: Long = 10_000 //10S

    private var _bleScanDeviceList = ArrayList<String>()

    private val _bluetoothManager: BluetoothManager by lazy {
        _context.getSystemService(BluetoothManager::class.java)
    }

    private var _bluetoothAdapter = _bluetoothManager.adapter
    private var _bluetoothScaner = _bluetoothAdapter.bluetoothLeScanner

    private val looper = Looper.getMainLooper()
    private val handler = Handler(looper)

    fun isBluetoothEnable(): Boolean {
        _bluetoothAdapter = _bluetoothManager.adapter
        _bluetoothScaner = _bluetoothAdapter.bluetoothLeScanner
        if( _bluetoothAdapter == null ){
            return false
        }
        return _bluetoothAdapter.isEnabled
    }

    @SuppressLint("MissingPermission")
    fun isDiscovery() : Boolean {
        if( _bluetoothAdapter == null ){
            return false;
        }
        return _bluetoothAdapter.isDiscovering
    }

    @SuppressLint("MissingPermission")
    fun scanLeDevice(uuidFilter : List<UUID>?,
                     onScanStart : () -> Unit,
                     onScanStop: () -> Unit,
                     onDevcieFound : ( bleDevice : EnvIIBleDevice ) -> Unit){
        if( _bluetoothAdapter == null ){
            Log.e(TAG, "BluetoothAdapter is null")
            return
        }

        val scanFilter = mutableListOf<ScanFilter>()
        uuidFilter?.let {
            for( uuid in uuidFilter ){
                val filter = ScanFilter.Builder().setServiceUuid(ParcelUuid(uuid))
                scanFilter.add(filter.build())
            }
        }

        val scanSetting = ScanSettings.Builder()
            .setScanMode(ScanSettings.SCAN_MODE_BALANCED)
            .build()

        if( !_scanning ){
            handler.postDelayed({
                _scanning = false
                onScanStop()
                _bluetoothScaner.stopScan(object : ScanCallback(){})
            }, _SCAN_PERIOD)
            _scanning = true
            _bleScanDeviceList.clear()
            onScanStart()
            _bluetoothScaner.startScan( scanFilter, scanSetting , object : ScanCallback(){
                override fun onBatchScanResults(results: MutableList<ScanResult>?) {
                    results?.let {
                        for( result in it ){
                            processScanResult(result){ res->
                                val bleDevice = EnvIIBleDevice(
                                    context =  _context,
                                    bluetoothDevice =  res.device,
                                    bluetoothRssi =  res.rssi
                                )
                                onDevcieFound( bleDevice )
                            }
                        }
                    }

                }

                override fun onScanResult(callbackType: Int, result: ScanResult?) {

                    processScanResult(result){res->
                        val bleDevice = EnvIIBleDevice(
                            context =  _context,
                            bluetoothDevice =  res.device,
                            bluetoothRssi =  res.rssi
                        )
                        Log.e(TAG, "onScanResult:${res.device.name}, address${res.device.address}")
                        onDevcieFound( bleDevice )
                    }
                }

                override fun onScanFailed(errorCode: Int) {

                }
            })
        }else{
            _scanning = false;
            onScanStop()
            _bluetoothScaner.stopScan(object : ScanCallback(){})
        }
    }

    @SuppressLint("MissingPermission")
    private fun processScanResult(result: ScanResult?, onResult: (result: ScanResult) -> Unit){
        result?.let {
            if( _bleScanDeviceList.contains(it.device.address) ){
                return
            }
            _bleScanDeviceList.add(it.device.address)
            onResult(it)
        }
    }
}